package com.example.mysql4droidplus;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabContentFactory;
import android.util.*;
import android.view.*;
import android.widget.*;
import android.support.v4.app.*;
import android.support.v4.widget.*;
import android.app.AlertDialog;
import android.content.*;

import java.io.*;

import android.database.sqlite.*;
import android.database.*;

public class MainActivity extends FragmentActivity implements OnPageChangeListener, OnTabChangeListener, View.OnClickListener {
	private final String sqlGetTableName = "SELECT name FROM sqlite_master WHERE TYPE='table' ORDER BY name;";
	
	private ViewPager vpPager = null;
	private TabHost tabHost = null;
	private DrawerLayout drawerLayout = null;
	private ExpandableListView expandableListView = null;
	private Button btnOpenDatabase = null;
	private Button btnRefreshList = null;
	private HorizontalScrollView scrollView = null;
	
	private List<Fragment> listFragments = new LinkedList<Fragment>();
	private List<String> listDatabasePath = null;
	private List<String> tabList = new LinkedList<String>(); 
	private List<String> expandableListViewGroupArray = new LinkedList<String>();
	private List<LinkedList<String>> expandableListViewChildArray = new LinkedList<LinkedList<String>>();
	private FragmentAdapter fragmentAdapter = null;
	private ExpandableListViewAdapter expandableListViewAdapter = null;
	private ActionBarDrawerToggle actionBarDrawerToggle = null;
	private int counter = 0;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		init();
	}

	private void init(){
		scrollView = (HorizontalScrollView)findViewById(R.id.maictivity_scrollview);
		
		// init viewpager
		vpPager = (ViewPager)findViewById(R.id.vpPage);
		fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(), listFragments);
		vpPager.setAdapter(fragmentAdapter);
		// vpPager.setCurrentItem(0);
		
		tabHost = (TabHost)findViewById(R.id.tabhost);
		tabHost.setup();
		/*addSqlTab();
		addSqlTab();addSqlTab();
		addSqlTab();addSqlTab();*/
		
		// expandableListView
		// test data
		/*expandableListViewGroupArray.add("Group0");
		expandableListViewGroupArray.add("Group1");
		expandableListViewGroupArray.add("Group2");
		LinkedList<String> l0 = new LinkedList<String>();
		l0.add("Student");
		l0.add("Course");
		l0.add("SC");
		l0.add("Other");
		expandableListViewChildArray.add(l0);
		LinkedList<String> l1 = new LinkedList<String>();
		l1.add("Staff");
		l1.add("Salary");
		l1.add("Information");
		l1.add("TestTable");
		expandableListViewChildArray.add(l1);
		LinkedList<String> l2 = new LinkedList<String>();
		l2.add("Uername");
		l2.add("Password");
		l2.add("Secure question");
		l2.add("Mail address");
		expandableListViewChildArray.add(l2);*/
		// Load last state
		listDatabasePath = loadLastDatabaseName();
		if(null == listDatabasePath)
			listDatabasePath = new LinkedList<String>();
		for(String path : listDatabasePath){
			addDatabaseToList(path);
		}
		expandableListView = (ExpandableListView)findViewById(R.id.activitymainExpandableListView1);
		expandableListViewAdapter = new ExpandableListViewAdapter(this, expandableListViewGroupArray, expandableListViewChildArray);
		expandableListView.setAdapter(expandableListViewAdapter);
		
		// drawer 
		drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
		getActionBar().setHomeButtonEnabled(true);
		getActionBar().setDisplayHomeAsUpEnabled(true);
		actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_back, R.string.hello_world, R.string.hello_world);
		actionBarDrawerToggle.syncState(); 
		drawerLayout.setDrawerListener(actionBarDrawerToggle);
		btnOpenDatabase = (Button)findViewById(R.id.activitymainButtonOpenDatabase);
		btnRefreshList = (Button)findViewById(R.id.activitymainButtonRefreshList);
		btnOpenDatabase.setOnClickListener(this);
		btnRefreshList.setOnClickListener(this);
		if(listDatabasePath.size() == 0){
			drawerLayout.openDrawer(Gravity.LEFT);
		}
		
		// listener
		vpPager.setOnPageChangeListener(this);
		tabHost.setOnTabChangedListener(this);
	}
	
	private void addSqlTab(String dbPath){
		FragmentSQL_Editor fEditor = new FragmentSQL_Editor();
		fEditor.dbPath = dbPath;
		/*Bundle bundle = new Bundle();
		bundle.putString("dbPath", dbPath);
		fEditor.setArguments(bundle);*/
		listFragments.add(fEditor);
		fragmentAdapter.notifyDataSetChanged();
		String id = "Query" + counter + ".sql";
		tabList.add(id);
		TabHost.TabSpec t = tabHost.newTabSpec(id);
		t.setIndicator(id);
		// t.setContent(R.id.tab1);
		TabContentFactory contentFactory  = new TabContentFactory() {
			
			@Override
			public View createTabContent(String tag) {
				View view = getLayoutInflater().inflate(R.layout.tabhost_custom, null);
				return view;
			}
		};
		t.setContent(contentFactory);
		// View view = getLayoutInflater().inflate(R.layout.tabhost_custom, null);
		// t.setIndicator(view);
		counter ++;
		tabHost.addTab(t);
		configTabWidth();
		tabHost.setCurrentTab(tabList.size() - 1);
		vpPager.setCurrentItem(listFragments.size() - 1);
		
		new Handler().post(new Runnable() {  
		    @Override  
		    public void run() {  
		        scrollView.fullScroll(ScrollView.FOCUS_RIGHT);  
		    }  
		});  
		
	}
	
	private void addDatabaseToList(String path){
		expandableListViewGroupArray.add(new File(path).getName());
		LinkedList<String> child = getDatabaseTableName(path);
		if(null == child)
			expandableListViewChildArray.add(new LinkedList<String>());
		else
			expandableListViewChildArray.add(child);
	}
	
	private void removeDatabaseFromList(int groupId){
		String oldPath = listDatabasePath.remove(groupId);
		// update expandableListView
		expandableListViewChildArray.remove(groupId);
		expandableListViewGroupArray.remove(groupId);
		expandableListViewAdapter.notifyDataSetChanged();
		// update viewpager and tabhost
		List<Integer> removeList = new LinkedList<Integer>();
		int n = 0;
		while(n < listFragments.size()){
			if(oldPath.equals(((FragmentCollect)listFragments.get(n)).dbPath)){
				listFragments.remove(n);
				removeList.add(n);
			}else{
				n ++;
			}
		}
		fragmentAdapter.notifyDataSetChanged();
		/*for(int i = 0; i < tabHost.getTabWidget().getChildCount(); i ++){
			Log.i("Test Delete tag", "i=" + i + " c=" + tabHost.getTabWidget().getChildCount());
			if(oldPath.equals(((FragmentCollect)listFragments.get(i)).dbPath)){
				Log.i("Test Delete tag", "delete ");
				isNeedDelete[i] = true;
				listFragments.remove(i);
				i --;
			}
		}*/
		tabHost.setCurrentTab(0);
		tabHost.clearAllTabs();
		tabHost.getTabWidget().removeAllViews();
		for(Integer i : removeList)	{// TODO : my keyboard is bugging ...
			tabList.remove(i.intValue());
			Log.i("delete event", "delete tabList : " + i);
			Log.i("delete event", "tabList.size = " + tabList.size());
		}
		/*for(int i = 0; i < isNeedDelete.length; i ++){
			if(!isNeedDelete[i]){
				String tag = tabList.get(i);
				newTabList.add(tag);
				TabHost.TabSpec t = tabHost.newTabSpec(tag);
				t.setIndicator(tag);
				t.setContent(R.id.tab1);
				tabHost.addTab(t);
			}
		}*/
		// tabList = newTabList;
		// tabHost.setup();
		TabContentFactory contentFactory  = new TabContentFactory() {
			
			@Override
			public View createTabContent(String tag) {
				View view = getLayoutInflater().inflate(R.layout.tabhost_custom, null);
				return view;
			}
		};
		for(String newTag : tabList){
			TabHost.TabSpec t = tabHost.newTabSpec(newTag);
			t.setIndicator(newTag);
			t.setContent(contentFactory);
			tabHost.addTab(t);
			Log.i("tanHost count :", "" + tabHost.getTabWidget().getTabCount());
		}
		// tabHost.getTabWidget().invalidate();
		configTabWidth();
	}
	
	private List<String> loadLastDatabaseName(){
		SharedPreferences sp = getSharedPreferences("lastDatabase", Context.MODE_PRIVATE);
		if(null == sp)
			return null;
		int num = sp.getInt("count", -1);
		if(-1 == num)
			return null;
		List<String> list = new LinkedList<String>();
		for(int i = 0; i < num; i ++){
			String kName = "lastDb" + i;
			String dbPath = sp.getString(kName, "");
			list.add(dbPath);
		}
		return list;
	}
	
	private LinkedList<String> getDatabaseTableName(String dbPath){
		SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath, null, 0);
		if(db == null)
			return null;
		Cursor c = db.rawQuery(sqlGetTableName, null);
		LinkedList<String> table = new LinkedList<String>();
		while(c.moveToNext()){
			table.add(c.getString(0));
		}
		return table;
	}
	
	private void configScrollView(){
		int offset = tabHost.getCurrentTab() * 300 - 50;
		scrollView.smoothScrollTo(offset, 0);
		return ;
	}
	
	private void configTabWidth(){
		// Toast.makeText(this, n + "", Toast.LENGTH_SHORT).show();
		DisplayMetrics dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		// int widthPixels= dm.widthPixels;
		// int heightPixels= dm.heightPixels;
		// float density = dm.density;
		// float screenWidth = widthPixels * density ;
		// float screenHeight = heightPixels * density ; 
		TabWidget tabw = (TabWidget)findViewById(android.R.id.tabs);
		if(tabw.getChildCount() == 0)
			return ;
		if(300 * tabw.getChildCount() >= dm.widthPixels){
			tabw.getChildAt(0).setMinimumWidth(300);
		} else {
			tabw.getChildAt(0).setMinimumWidth(dm.widthPixels / tabw.getChildCount());
		}
	}
	
	private FragmentCollect getCurrentFragment(){
		if(tabHost.getTabWidget().getChildCount() == 0)
			return null;
		int n = tabHost.getCurrentTab();
		return (FragmentCollect)listFragments.get(n);
	}
	
	private void showFileChooser() {
		Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
		intent.setType("*/*"); 
		intent.addCategory(Intent.CATEGORY_OPENABLE);

		try {
			startActivityForResult( Intent.createChooser(intent, "Select a database to open"), 86);
		} catch (android.content.ActivityNotFoundException ex) {
			Toast.makeText(this, "Please install a File Manager.",  Toast.LENGTH_SHORT).show();
		}
	}
	
	public void showInfoDialog(String dbPath) {
		View view = getLayoutInflater().inflate(R.layout.database_information, null);
		TextView txtPath = (TextView)view.findViewById(R.id.textView_dbPath);
		TextView txtSize = (TextView)view.findViewById(R.id.textView_filesize);
		txtPath.setText(dbPath);
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(dbPath);
			txtSize.setText(fis.available() + "b");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		AlertDialog.Builder b = new AlertDialog.Builder(this);
		b.setTitle("Database Information ");
		b.setView(view);
		b.setPositiveButton("OK", new DialogInterface.OnClickListener() {			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		b.show();
	}
	
	public void onExpandableListViewItemClick(final int groupId, View v){
		if(v.getId() == R.id.customgroupButton3){
			// start new fragment
			addSqlTab(listDatabasePath.get(groupId));
			drawerLayout.closeDrawer(Gravity.LEFT);
			return ;
		}
		if(v.getId() == R.id.customgroupButton2){
			AlertDialog.Builder b = new AlertDialog.Builder(this);
			b.setTitle("Warnning !");
			b.setMessage("Close this database means close all the tabs attach on this database too, do you want to close this database without save data ?");
			b.setPositiveButton("Yes", new DialogInterface.OnClickListener() {				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					removeDatabaseFromList(groupId);
					dialog.dismiss();
				}
			});
			b.setNegativeButton("No", new DialogInterface.OnClickListener() {				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			b.show();
			return ;
		}
		if(v.getId() == R.id.customgroupButton1){
			// info 
			showInfoDialog(listDatabasePath.get(groupId));
			return ;
		}
	}


	@Override
	public void onClick(View p1) {
		switch(p1.getId()){
			case R.id.activitymainButtonOpenDatabase:
				showFileChooser();
				break;
			case R.id.activitymainButtonRefreshList:
				expandableListViewGroupArray.clear();
				expandableListViewChildArray.clear();
				for(String path : listDatabasePath)
					addDatabaseToList(path);
				expandableListViewAdapter.notifyDataSetChanged();
				Toast.makeText(this, "Table names have been update", Toast.LENGTH_SHORT).show();
				break;
		}
	}

	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onPageScrollStateChanged(int arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onPageSelected(int arg0) {
		Log.i("Page Event :", "page -> " + arg0);
		if(arg0 >= tabHost.getTabWidget().getChildCount())
			return ;
		Log.i("Tab count : ", "" + tabHost.getTabWidget().getChildCount());
		tabHost.setCurrentTab(arg0);
		configScrollView();
	}

	@Override
	public void onTabChanged(String tabId) {
		Log.i("test", tabId);
		for(int i = 0; i < tabList.size(); i ++){
			if(tabId.equals(tabList.get(i))){
				vpPager.setCurrentItem(i);
				configScrollView();
				break;
			}
		}
	}
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
			// Toast.makeText(this, "onClick", Toast.LENGTH_SHORT).show();
			return true;
        }
        // Handle your other action bar items...
        switch (item.getItemId()) {
		case R.id.menu_exec:
			FragmentCollect fragmentCollect = getCurrentFragment();
			if(null == fragmentCollect)
				break;
			switch (fragmentCollect.type) {
			case 0:
				FragmentSQL_Editor fEditor = (FragmentSQL_Editor)fragmentCollect;
				SQLException e = fEditor.execSQL();
				if(null == e){
					Toast.makeText(this, "Execute SQL successful !", Toast.LENGTH_SHORT).show();
				}else{
					AlertDialog.Builder b = new AlertDialog.Builder(this);
					b.setTitle("Execute failed !");
					b.setMessage(e.getMessage());
					b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					});
					b.setNegativeButton("Copy", new DialogInterface.OnClickListener() {						
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// copy error logs to clipboard
							dialog.dismiss();
						}
					});
					b.show();
				}
				break;

			default:
				break;
			}
			break;

		default:
			break;
		}

        return super.onOptionsItemSelected(item);
    }

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch(requestCode){
			case 86:
				if(RESULT_OK == resultCode){
					String path = FileUtils.getPath(this, data.getData());
					Log.i("path", path);
					if(null == path)
						return ;
					if(path.endsWith(".db")){
						for(String s : listDatabasePath)
							if(s.equals(path))
								return ;
						listDatabasePath.add(path);
						// expandableListViewGroupArray.add(new File(path).getName());
						addDatabaseToList(path);
						expandableListViewAdapter.notifyDataSetChanged();
					}
				}
				break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	
	@Override
	protected void onDestroy() {
		// save dbpath state
		SharedPreferences sp = getSharedPreferences("lastDatabase", Context.MODE_PRIVATE);
		SharedPreferences.Editor ed = sp.edit();
		ed.clear();
		int n = listDatabasePath.size(), i = 0;
		ed.putInt("count", n);
		for(String content : listDatabasePath){
			ed.putString("lastDb" + i++, content);
		}
		ed.commit();
		super.onDestroy();
	}

}
